4735 2020-01-16 2024-10-15
一、BeanFactoryPostProcessor
1、概述
正式开始介绍之前,我们先了解下 BeanFactoryPostProcessor 的用法。
BeanFactoryPostProcessor 接口跟 BeanPostProcessor 类似,可以对bean的定义(BeanDefinition)进行处理。也就是说,Spring IoC容器允许BeanFactoryPostProcessor在 容器实际实例化任何其他bean之前 读取配置元数据,并有可能修改它(BeanDefinition)。
如果你愿意,你可以配置多个BeanFactoryPostProcessor。你还能通过@Order来控制BeanFactoryPostProcessor的执行循序。如果你想改变实际的的bean实例(例如从配置元数据创建对象),那么你最好使用 BeanPostProcessor,而不是BeanFactoryPostProcessor 。
同样地,BeanFactoryPostProcessor的作用域范围是容器级的,它只和你所使用的容器有关。如果你在容器中定义一个BeanFactoryPostProcessor,它仅仅对此容器中的bean进行后置处理。BeanFactoryPostProcessor不会对定义在另一个容器的bean进行后置处理,即使这两个容器都是在同一层次上。在Spring中存在对于BeanFactoryPostProcessor的典型应用,比如 PropertyPlaceholderConfigurer。
2、PropertyPlaceholderConfigurer
BeanFactoryPostProcessor的典型应用:PropertyPlaceholderConfigurer。有时候,阅读Spring的bean描述文件时,你也许会遇到类似如下的一些配置:
<bean id="testBean" class="xiaokui.TestBean">
<property name="name" value="${another.name}"/>
</bean>
其中竟然出现了变量应用:${another.name}。这就是Spring的分散配置,可以在另外的配置文件中为another.name指定值。当访问testBean.name时就会自动赋值过去,但Spring怎么知道存在这样的配置文件呢?这就要靠PropertyPlaceholderConfigurer这个类的bean了。
<bean id="myHandler" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>xiaokui/another.properties</value>
</list>
</property>
</bean>
在这个bean中指定了配置文件为xiaokui/another.properties。到这里似乎找到了问题的答案了,但是其实还有个问题。这个“myHandler”只不过是Spring管理的一个bean,并没有被别的bean或者对象应用,Spring的BeanFactory是怎么知道要从这个bean中获取配置信息的呢?
查看层级结构可以看出PropertyPlaceholderConfigurer这个类间接继承了BeanFactoryPostProcessor接口。这是一个很特别的接口,当Spring加载任何实现了这个接口的bean的配置时,都会在bean工厂 **载入所有bean的配置之后执行 **PostProcessBeanFactory方法。
在PropertyResourceConfigurer类中实现了postProcessBeanFactory方法,在此方法中先后调用了mergeProperties、convertProperties、processProperties这3个方法,分别得到配置,将得到的配置转换为合适的类型,最后将配置内容告知BeanFactory。
// Spring高版本推荐使用 PropertySourcesPlaceholderConfigurer
// 来自类 PropertyPlaceholderConfigurer,该类实现了BeanFactoryPostProcessor接口
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
try {
Properties mergedProps = mergeProperties();
// Convert the merged properties, if necessary.
convertProperties(mergedProps);
// Let the subclass process the properties.
processProperties(beanFactory, mergedProps);
}
catch (IOException ex) {
throw new BeanInitializationException("Could not load properties", ex);
}
}
/**
* Visit each bean definition in the given bean factory and attempt to replace ${...} property
* placeholders with values from the given properties.
*/
@Override
protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props)
throws BeansException {
StringValueResolver valueResolver = new PlaceholderResolvingStringValueResolver(props);
doProcessProperties(beanFactoryToProcess, valueResolver);
}
正是通过实现BeanFactoryPostProcessor接口,BeanFactory会实例化任何bean之前获得配置信息,从而能够正确解析bean描述文件中的变量应用。
3、自定义BeanFactoryPostProcessor
我们以实现一个BeanFactoryPostProcessor,去除潜在的“流氓”属性值的功能来展示自定义BeanFactoryPostProcessor的创建以及使用,例如bean定义中包含sb这样的字眼字段。
public class TestBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
private Set<String> obscenties;
public TestBeanFactoryPostProcessor() {
this.obscenties = new HashSet<>();
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 容器级别,因此只会被执行一次
String[] beanNames = beanFactory.getBeanDefinitionNames();
for (String beanName : beanNames) {
BeanDefinition bd = beanFactory.getBeanDefinition(beanName);
StringValueResolver valueResolver = new StringValueResolver() {
@Override
public String resolveStringValue(String strVal) {
if (isObscene(strVal)) {
return "*****";
}
return strVal;
}
};
BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(valueResolver);
visitor.visitBeanDefinition(bd);
}
}
public boolean isObscene(String str) {
String potentialObscenity = str.toUpperCase();
return this.obscenties.contains(potentialObscenity);
}
}
// 来自类 BeanDefinitionVisitor,遍历 BeanDefinition,做你想做的任何事情!
public void visitBeanDefinition(BeanDefinition beanDefinition) {
visitParentName(beanDefinition);
visitBeanClassName(beanDefinition);
visitFactoryBeanName(beanDefinition);
visitFactoryMethodName(beanDefinition);
visitScope(beanDefinition);
if (beanDefinition.hasPropertyValues()) {
visitPropertyValues(beanDefinition.getPropertyValues());
}
if (beanDefinition.hasConstructorArgumentValues()) {
ConstructorArgumentValues cas = beanDefinition.getConstructorArgumentValues();
visitIndexedArgumentValues(cas.getIndexedArgumentValues());
visitGenericArgumentValues(cas.getGenericArgumentValues());
}
}
二、invokeBeanFactoryPostProcessors*
了解了 BeanFactoryPostProcessor 的用法后,便可以深入研究BeanFactoryPostProcessor的调用过程了(前面只是定义,这里才是调用)。
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// 我们重点关注下这一行,这一这里的getBeanFactoryPostProcessors为0,即内置为0个
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();
// 一般都是走这个逻辑
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
// 这里对内置BeanDefinitionRegistryPostProcessor特殊处理
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
// 寻找我们自定义的BeanDefinitionRegistryPostProcessor,而非内置
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
// 排序并逐个调用,这里的排序规则是根据getDependencyComparator里定义的规则
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
// 这里对于@Ordered的处理
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
// 排序并逐个调用
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// @PriorityOrdered 早于 @Ordered 实例化
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
// 注意,统一在这一步初始化@Configuration中的@Bean
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}
从上面的方法中我们看到,对于BeanFactoryPostProcessor的处理主要分为两种情况进行,一个是对于BeanDefinitionRegistryPostProcessor类的特殊处理,另一种是对普通BeanFactoryPostProcessor进行处理。而对于每种情况都需要考虑硬编码/内置的后处理器、通过配置注入的后处理器以及调用顺序的问题。
1、BeanDefinitionRegistryPostProcessor
// BeanDefinitionRegistryPostProcessor优先于BeanFactoryPostProcessor调用
// 需要注意的是该类是BeanFactoryPostProcessor的父类,所以同一个BeanFactoryPostProcessor不会调用两次
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
2、BeanFactoryPostProcessor
@FunctionalInterface
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
3、ConfigurationClassPostProcessor*
这个类或许读者感到陌生,但是对于@Configuration、@Bean应该不陌生吧。当我们使用注解驱动方式编程时,那么此时就会先调用postProcessBeanDefinitionRegistry方法、然后再调用postProcessBeanFactory,以扫描被@Configuration类下的所有@Bean,但不会扫描@Component。
// 这个bean在Spring的beanName
// 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
/**
* Derive further bean definitions from the configuration classes in the registry.
*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
}
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + registry);
}
this.registriesPostProcessed.add(registryId);
// 这里只是寻找@Configuration并注册,此时还未进行初始化
processConfigBeanDefinitions(registry);
}
/**
* Prepare the Configuration classes for servicing bean requests at runtime
* by replacing them with CGLIB-enhanced subclasses.
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
int factoryId = System.identityHashCode(beanFactory);
if (this.factoriesPostProcessed.contains(factoryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + beanFactory);
}
this.factoriesPostProcessed.add(factoryId);
if (!this.registriesPostProcessed.contains(factoryId)) {
// BeanDefinitionRegistryPostProcessor hook apparently not supported...
// Simply call processConfigurationClasses lazily at this point then.
processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
}
// 增强,即使用CGLIB代理
// 因为@Configuration注解中有默认属性boolean proxyBeanMethods() default true;
enhanceConfigurationClasses(beanFactory);
// 这里还没有进行初始化,而是添加对ImportAwar的支持
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}
// 省略其他方法....
}
三、registerBeanPostProcessors*
上文中提到了BeanFactoryPostProcessor的调用,现在我们来探索下BeanPostProcessor,这是一个很重要的步骤,也是很多功能BeanFactory不支持的重要原因。
Spring中大部分功能都是通过后处理器的方式进行扩展的,这是Spring框架的一个特性,但是在BeanFactory中其实并没有实现后处理器的自动注册,所以在调用的时候如果没有进行手动注册,那么是不能使用的。但是在ApplicationContext中却添加了自动注册功能,如自定义这样一个后处理器
public class MyBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
// 注意获取该bean,只会调用一次,后续直接从缓存返回
System.out.println("获取bean:" + beanName + "," + bean);
// 继续让其他BeanPostProcessor处理,false则阻止
return true;
}
}
在配置文件中添加配置
<bean class="xiaokui.MyBeanPostProcessor"/>
那么使用BeanFactory方式进行Spring的bean的加载时不会有任何改变的,但是使用ApplicationContext方式获取bean的时候会在获取每个bean时打印相关信息,而这个特性就是在registerBeanPostProcessor方法中完成的。
我们继续探索registerBeanPostProcessor方法的实现。
// 初始化并注册
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// Register BeanPostProcessorChecker that logs an info message when
// a bean is created during BeanPostProcessor instantiation, i.e. when
// a bean is not eligible for getting processed by all BeanPostProcessors.
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, register the BeanPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// Next, register the BeanPostProcessors that implement Ordered.
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// Now, register all regular BeanPostProcessors.
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// Finally, re-register all internal BeanPostProcessors.
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// Re-register post-processor for detecting inner beans as ApplicationListeners,
// moving it to the end of the processor chain (for picking up proxies etc).
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
首先我们会发现,对于BeanPostProcessor的处理与BeanFactoryPostProcessor的处理极为相似。
对于beanFactory的注册,也不是直接注册就可以的。在Spring中支持对于BeanPostProcessor的排序,比如根据priorityOrdered进行排序、根据Ordered进行排序或者无序,而Spring在BeanPostProcessor的激活顺序的时候就会考虑顺序的问题而先进行排序。
特别的,有如下输出:
-
priorityOrderedPostProcessors:
- CommonAnnotationBeanPostProcessor
- AutowiredAnnotationBeanPostProcessor
-
internalPostProcessors:
- CommonAnnotationBeanPostProcessor
- AutowiredAnnotationBeanPostProcessor
-
orderedPostProcessors:
- internalAutoProxyCreator
-
nonOrderedPostProcessors:
- myBeanPostProcessor
四、initMessageSource
在进行这个方法的解析之前,我们同样先来回顾Spring国际化的使用方法。
假设我们正在开发一个支持多国语言的WEB应用程序,要求系统能够根据客户端的系统语言类型返回对于的界面:英文的操作系统返回英文界面,而中文的操作系统则返回中文界面——这便是典型的il8n国际化问题。对于有国际化要求的应用系统,我们不能简单地采用特殊编码的方式编写用户界面信息、保存信息等内容,而必须为这些需要国际化的信息进行特殊处理。简单来说,就是为每种语言提供一套相应的资源文件,并以规范化命名的方式保存在特定的目录中,由系统自动根据客户端语言选择适合的资源文件。
国际化信息也成为本地化信息,一般需要两个条件才可以确定一个特定类型的本地化信息,它们分别是“语言类型”和“国际/地区的类型”。如中文本地化信息既有中国大陆地区的中文,又有总共台湾地区、中国香港地区的中文,还有新加坡地区的中文。Java通过java.tuil.Locale类表示一个本地化对象,它允许通过语言参数和国家/地区参数创建一个确定的本地化对象。
java.util.Locale是表示语言和国建/地区的信息的本地化类,它是创建国际化应用的基础。下面给出几个创建本地化对象的实例
// 带有语言和国家/地区信息的本地化对象
Local local1 = new Locale("zh", "CN");
// 只有语言信息的本地化对象
Local local2 = new Locale("zh“);
// 等同于new Locale("zh", "CN");
Local local3 = Locale.CHINA;
// 等同于new Locale("zh");
Local local4 = Locale.CHINESE;
// 获取本地系统默认的本地化对象
Local local5 = Locale.getDefault();
更多有关资源国际化的分析,等到用时再来补充。
protected void initMessageSource() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
// 如果在配置中已经指定了 messageSource bean
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
// Make MessageSource aware of parent MessageSource.
if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
if (hms.getParentMessageSource() == null) {
// Only set parent context as parent MessageSource if no parent MessageSource
// registered already.
hms.setParentMessageSource(getInternalParentMessageSource());
}
}
if (logger.isDebugEnabled()) {
logger.debug("Using MessageSource [" + this.messageSource + "]");
}
}
else {
// 如果用户没有定义messageSource bean
// Use empty MessageSource to be able to accept getMessage calls.
DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME +
"': using default [" + this.messageSource + "]");
}
}
}
五、initApplicationEventMulticaster
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 如果在配置中指定了相应bean,APPLICATION_EVENT_MULTICASTER_BEAN_NAME 值为applicationEventMulticaster
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isDebugEnabled()) {
logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
// 否则使用默认的事件广播器
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
"': using default [" + this.applicationEventMulticaster + "]");
}
}
}
这是观察者模式的一个应用,当事件发生时会主动通知注册在广播器上的监听器。
六、onRefresh
protected void onRefresh() throws BeansException {
// For subclasses: do nothing by default.
}
// AbstractRefreshableWebApplicationContext类进行了重写
@Override
protected void onRefresh() {
// 这里初始化了主题资源
this.themeSource = UiApplicationContextUtils.initThemeSource(this);
}
七、registerListeners
// 注册ApplicationListener
protected void registerListeners() {
// Register statically specified listeners first.
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// Publish early application events now that we finally have a multicaster...
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
八、finishBeanFactoryInitialization
完成BeanFactory的初始化工作,其中包括ConversionService的设置、配置冻结以及非延迟加载的bean初始化工作。
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
// 冻结所有的bean定义,说明注册的bean定义将不被修改或任何进一步的处理
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
// 初始化剩下的单实例(非惰性)
beanFactory.preInstantiateSingletons();
}
首先我们来了解一下ConversionService类所提供的作用。
1、ConversionService的设置
之前我们提到过使用使用自定义的类型转换器(CustomEditorConfigurer)从String转换为Date的方式,那么在Spring中还提供了另一种转换方式:使用Converter。
public interface ConversionService {
boolean canConvert(@Nullable Class<?> sourceType, Class<?> targetType);
boolean canConvert(@Nullable TypeDescriptor sourceType, TypeDescriptor targetType);
@Nullable
<T> T convert(@Nullable Object source, Class<T> targetType);
@Nullable
Object convert(@Nullable Object source, @Nullable TypeDescriptor sourceType, TypeDescriptor targetType);
}
2、freezeConfiguration
冻结所有的bean定义,说明注册的bean定义将不被修改或任何进一步的处理。
public void freezeConfiguration() {
this.configurationFrozen = true;
synchronized (this.beanDefinitionMap) {
this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames);
}
}
3、preInstantiateSingletons
ApplicationContext实现的默认行为就是 在启动时将所有单例bean提前进行实例化。
提前实例化意味着初始化过程的一部分,ApplicationContext实例会创建并配置所有的单例bena。通常情况下这是一件好事,因为这样在配置中的任何错误就会即可被发现(否则的话可能要话几个小时甚至几天)。而这个实例化过程就是在preInstantiateSingletons方法中完成的。
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isInfoEnabled()) {
this.logger.info("Pre-instantiating singletons in " + this);
}
List<String> beanNames;
synchronized (this.beanDefinitionMap) {
beanNames = new ArrayList<String>(this.beanDefinitionNames);
}
// Trigger initialization of all non-lazy singleton beans...
// Spring开始下狠手了,初始化所有 非lazy bean
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
public Boolean run() {
return ((SmartFactoryBean<?>) factory).isEagerInit();
}
}, getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
else {
getBean(beanName);
}
}
}
}
九、finishRefresh
在Spring中还提供了Lifecycle接口,Lifecycle包含start/stop方法,实现此接口后Spring会保证在启动的时候调用start方法开始生命周期,并在Spring关闭的时候调用stop方法来结束生命周期。而ApplicationContext的初始化最后一步正式保证这一功能的实现。
protected void finishRefresh() {
// Clear context-level resource caches (such as ASM metadata from scanning).
clearResourceCaches();
// 1.Initialize lifecycle processor for this context.
initLifecycleProcessor();
// 2.Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh();
// 3.Publish the final event.
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
LiveBeansView.registerApplicationContext(this);
}
1、initLifecycleProcessor
当ApplicationContext启动或停止时,它会通过LifecycleProcessor来跟所有生命bean的周期做状态更新,而在LifecycleProcessor的使用前首先需要初始化。
/**
* Initialize the LifecycleProcessor.
* Uses DefaultLifecycleProcessor if none defined in the context.
* @see org.springframework.context.support.DefaultLifecycleProcessor
*/
protected void initLifecycleProcessor() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
this.lifecycleProcessor =
beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
if (logger.isDebugEnabled()) {
logger.debug("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
}
}
else {
DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
defaultProcessor.setBeanFactory(beanFactory);
this.lifecycleProcessor = defaultProcessor;
beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate LifecycleProcessor with name '" +
LIFECYCLE_PROCESSOR_BEAN_NAME +
"': using default [" + this.lifecycleProcessor + "]");
}
}
}
2、onRefresh
启动所有实现Lifecycle接口的bean。
public void onRefresh() {
startBeans(true);
this.running = true;
}
private void startBeans(boolean autoStartupOnly) {
Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
Map<Integer, LifecycleGroup> phases = new HashMap<Integer, LifecycleGroup>();
for (Map.Entry<String, ? extends Lifecycle> entry : lifecycleBeans.entrySet()) {
Lifecycle bean = entry.getValue();
if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
int phase = getPhase(bean);
LifecycleGroup group = phases.get(phase);
if (group == null) {
group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
phases.put(phase, group);
}
group.add(entry.getKey(), bean);
}
}
if (phases.size() > 0) {
List<Integer> keys = new ArrayList<Integer>(phases.keySet());
Collections.sort(keys);
for (Integer key : keys) {
phases.get(key).start();
}
}
}
3、publishEvent
当完成ApplicationContext初始化的时候,要通过Spring中的事件发布机制来发出ContextRefreshedEvent时间,以保证对应的监听器可以做进一步的逻辑处理
public void publishEvent(ApplicationEvent event) {
Assert.notNull(event, "Event must not be null");
if (logger.isTraceEnabled()) {
logger.trace("Publishing event in " + getDisplayName() + ": " + event);
}
getApplicationEventMulticaster().multicastEvent(event);
if (this.parent != null) {
this.parent.publishEvent(event);
}
}
这里举个例子,便于理解,如下
@Component
public class TestWebContextEvent implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("Spring发布事件" + event);
}
}
下篇我们将尝试通过一个例子从横向的角度看下bean的全生命周期,看下一个bean从诞生到消亡都经历了什么,每个环节我们都可以做些什么。
总访问次数: 5次, 一般般帅 创建于 2020-01-16, 最后更新于 2024-10-15
欢迎关注微信公众号,第一时间掌握最新动态!